iT邦幫忙

2024 iThome 鐵人賽

DAY 15
0
DevOps

《30天挑戰精通 PowerShell:從 Windows Server 到 Azure DevOps 自動化之旅》系列 第 15

Day 15 - 解釋 WinRM、PSSession、Invoke-Command

  • 分享至 

  • xImage
  •  

對應 30天挑戰精通 PowerShell 該書第 13 章「遠端控制:一對一及一對多」。

今天將書中介紹的 WinRM 概覽及個人使用筆記做整理,也將昨天沒有講完的 PSSession 及 Invoke-Command 做個結尾。


一、WinRM(Windows 遠端管理)

1. 什麼是 WinRM?

WinRM(Windows Remote Management)是 Microsoft 基於 WS-Management 通訊協定的實作,用於遠端管理 Windows 系統。它允許你透過網路與遠端電腦通訊,執行指令、存取資料,並進行系統管理。

WinRM 不是僅限於 PowerShell 使用。Microsoft 正逐漸將其應用到更多通訊管理方面,甚至包括目前使用其他協定的事物。基於這個理念,Microsoft 讓 WinRM 能夠把流量導引到多種管理應用程式,而不是只有 PowerShell。WinRM 扮演著調度者的角色:當流量導入時,WinRM 會決定哪個應用程式需要處理這些流量。所有的 WinRM 流量都會被標記上「接收的應用程式( recipient application )的名稱」,而這些應用程式必須向 WinRM 註冊為端點( endpoint ),讓 WinRM 能夠代替它們監聽「傳入的流量」。這意味著你需要在啟用 WinRM 的同時,還要指示 PowerShell 向 WinRM 註冊為一個端點。

你的系統上可能有數十個甚至數百個 WinRM 端點( PowerShell 將他們稱為會話組態,session configuration )。每個端點都能指向不同的應用程式,你甚至可以有多個端點指向同一個應用程式,但是提供不同的權限和功能。

概念示意圖

https://ithelp.ithome.com.tw/upload/images/20240929/20168708itdvrB8tL5.png

Client config

在 Client 端以管理者權限開啟 PowerShell 後執行 winrm get winrm/config/client 確認 WinRM client 的設定。

  • TrustedHosts:顯示所有設定的受信主機。
  • AllowUnencrypted:確認是否允許未加密的連接,通常應設為 false
  • 身份驗證設定(Auth):檢查是否啟用了適當的身份驗證方式,如 Negotiate、Kerberos。
PS C:\Users\kanglin> winrm get winrm/config/client
Client
    NetworkDelayms = 5000
    URLPrefix = wsman
    AllowUnencrypted = false
    Auth
        Basic = true
        Digest = true
        Kerberos = true
        Negotiate = true
        Certificate = true
        CredSSP = false
    DefaultPorts
        HTTP = 5985
        HTTPS = 5986
    TrustedHosts

Server config - service

在 Server 端以管理者權限開啟 PowerShell 後執行 winrm get winrm/config/service 確認 WinRM Server 端 service 的設定。

PS C:\Users\kanglinserver> winrm get winrm/config/service
Service
    RootSDDL = O:NSG:BAD:P(A;;GA;;;BA)(A;;GR;;;IU)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)
    MaxConcurrentOperations = 4294967295
    MaxConcurrentOperationsPerUser = 1500
    EnumerationTimeoutms = 240000
    MaxConnections = 300
    MaxPacketRetrievalTimeSeconds = 120
    AllowUnencrypted = false
    Auth
        Basic = false
        Kerberos = true
        Negotiate = true
        Certificate = false
        CredSSP = false
        CbtHardeningLevel = Relaxed
    DefaultPorts
        HTTP = 5985
        HTTPS = 5986
    IPv4Filter = *
    IPv6Filter = *
    EnableCompatibilityHttpListener = false
    EnableCompatibilityHttpsListener = false
    CertificateThumbprint
    AllowRemoteAccess = true

Server config - listener

查看所有 WinRM Listener 的詳細信息

PS C:\Users\kanglinserver> winrm enumerate winrm/config/listener
Listener
    Address = *
    Transport = HTTP
    Port = 5985
    Hostname
    Enabled = true
    URLPrefix = wsman
    CertificateThumbprint
    ListeningOn = 10.1.1.127, 127.0.0.1, ::1

2. 如何在 Client 端及 Server 端啟用和設定 WinRM?

Client 端(發起連線的電腦)需要設定:

1. 啟用 WinRM

執行該命令將正確設定防火牆規則和服務狀態,以確保 WinRM 正常運行。

Enable-PSRemoting -Force

2. 設定信任的主機 (TrustedHosts)

當 Client 端連接到非同網域的 Server(或工作組環境)時,需要在 Client 端設定 TrustedHosts 允許與指定的遠端電腦進行通訊。

Set-Item WSMan:\localhost\Client\TrustedHosts "遠端電腦的IP或主機名"

3. 檢查連線狀態

在設定完成後,您可以使用 Test-WsMan 命令來確認是否可以與目標 Server 成功連接。

Test-WsMan -ComputerName 遠端電腦的IP或主機名

Server 端(接受連線的電腦)需要設定:

1. 啟用 WinRM

執行該命令將正確設定防火牆規則和服務狀態,以確保 WinRM 正常運行。

Enable-PSRemoting -Force

2. 確保 WinRM Listener 正常運行

  • 查看所有 WinRM Listener 的詳細信息
winrm enumerate winrm/config/listener
  • 創建 HTTP Listener
winrm create winrm/config/listener?Address=*+Transport=HTTP
  • 創建 HTTPS Listener (需要 SSL 憑證)
winrm create winrm/config/listener?Address=*+Transport=HTTPS

3. 帳號密碼及權限配置

確保連接 Server 的帳號有足夠的權限執行所需的遠端命令。通常需要管理員權限,特別是對於執行特定的管理任務。然而 Client 若需要使用不同的帳號來連接 Server,可以使用 -Credential 參數來指定憑證。

範例:使用 Invoke-Command 提供憑證

該範例會跳出輸入帳號密碼的提示字窗

# 取得使用者憑證
$cred = Get-Credential

# 執行遠端指令
Invoke-Command -ComputerName "遠端電腦名或IP" -Credential $cred -ScriptBlock { Get-Process }
範例:建立 PSSession 時提供憑證

該範例會跳出輸入帳號密碼的提示字窗

# 取得使用者憑證
$cred = Get-Credential

# 建立 PSSession
$session = New-PSSession -ComputerName "遠端電腦名或IP" -Credential $cred

# 在 PSSession 中執行指令
Invoke-Command -Session $session -ScriptBlock { Get-Service }

# 關閉 PSSession
Remove-PSSession -Session $session
範例:指定使用者名稱和密碼

直接在腳本中指定使用者名稱和密碼,但需要注意安全性。

# 建立安全的密碼字串
$securePassword = ConvertTo-SecureString "您的密碼" -AsPlainText -Force

# 建立憑證物件
$cred = New-Object System.Management.Automation.PSCredential("使用者名稱", $securePassword)

# 使用憑證執行遠端指令
Invoke-Command -ComputerName "遠端電腦名或IP" -Credential $cred -ScriptBlock { Get-Process }

二、PSSession(PowerShell 會話)

1. 什麼是 PSSession?

PSSession 是一個與遠端電腦建立的持久連線,允許您在該連線中執行多個指令,而不必每次都重新建立連線。這在需要執行多個指令時可以提高效率。

Client 與 Server 透過 PSSession 的交互過程

https://ithelp.ithome.com.tw/upload/images/20240929/20168708UArs38dpOW.png

  1. Initiate PSSession( 發起 PSSession )
    Client 端的 PowerShell 發出建立 PSSession 的請求,例如 New-PSSession 或 Invoke-Command,在這一步,Client 開始嘗試與 Server 端建立連結,並準備進行驗證。
  2. TCP 連接初始化
    • TCP Connection SYN:Client 向 Server 發送一個 SYN(同步)請求( 標準的 TCP 三項交握第一步)。
    • TCP Connection SYN ACK:Server 收到 SYN 請求後,回應一個 SYN ACK(同步應答)消息,表示它已經準備好接受連接。
    • TCP Connection ACK:Client 端再次發送一個 ACK(確認)消息,最終完成三次握手,並正式建立 TCP 連接。
  3. 身份驗證請求
    • Authentication HTTP POST:TCP 連接建立後,Client 端會發送一個身份驗證請求( HTTP POST )。這一步通常涉及使用 WinRM 協議進行身份驗證,例如 Kerberos、NTLM 或其他協商身份驗證方式。
    • Authentication POST Response:Server 收到身份驗證請求後,會對其進行驗證,然後回應驗證結果。如果身份驗證成功,Client 端即可與 Server 建立會話。
  4. PSSession Initiated(PSSession 建立)
    驗證成功後,PSSession 正式建立,這個會話允許 Client 端向 Server 端傳送 PowerShell 命令並接收回應。
  5. PowerShell Command(發送 PowerShell 指令)
    一旦 PSSession 建立,Client 端可以發送遠端 PowerShell 指令,這些指令會透過已建立的 PSSession 來執行。
  6. PowerShell Command Output(返回 PowerShell 指令輸出)
    Server 端執行完指令後,會將執行結果通過 PSSession 回傳給 Client 端,並在 Client 的 PowerShell 中顯示結果。

2. 如何建立和管理 PSSession?

建立一個新的 PSSession:

$session = New-PSSession -ComputerName 遠端電腦的IP或主機名

查看當前的 PSSession:

Get-PSSession

在 PSSession 中執行指令:

Invoke-Command -Session $session -ScriptBlock { Get-Process }

進入 PSSession(互動式):

Enter-PSSession -Session $session

退出 PSSession:

在互動式會話中,輸入 Exit-PSSession 或簡寫 Exit

關閉 PSSession:

Remove-PSSession -Session $session

3. 範例

範例:在遠端電腦上獲取服務列表

# 建立 PSSession
$session = New-PSSession -ComputerName 192.168.1.100

# 在遠端會話中執行指令
Invoke-Command -Session $session -ScriptBlock { Get-Service }

# 關閉 PSSession
Remove-PSSession -Session $session

三、Invoke-Command

1. 什麼是 Invoke-Command?

  • Invoke-Command cmdlet 用於在本地遠端電腦上執行命令,並返回命令的所有輸出,包含錯誤訊息。
  • 可以使用一條 Invoke-Command 命令對多台電腦執行指令。
PS /Users/kanglin/code/30days> get-help Invoke-Command | more

NAME
    Invoke-Command

SYNOPSIS
    Runs commands on local and remote computers.

主要應用場景:

  • 遠端執行單一命令:
    使用 -ComputerName 在一台遠端電腦上運行單個命令。
  • 多次命令的遠端會話
    使用 New-PSSession 建立持久會話,然後使用 -Session 在會話中多次執行命令,適合多命令操作。
  • 跨多平台的遠端管理
    通過 SSH 進行跨平台(Windows、Linux、macOS)的遠端管理操作。

2. 如何使用 Invoke-Command?

在遠端電腦上執行指令:

Invoke-Command -ComputerName 遠端電腦的IP或主機名 -ScriptBlock { 指令或腳本區塊 }

使用 PSSession:

Invoke-Command -Session $session -ScriptBlock { 指令或腳本區塊 }

對多台電腦執行指令:

Invoke-Command -ComputerName PC1,PC2,PC3 -ScriptBlock { 指令或腳本區塊 }

3. 範例

範例:在多台遠端電腦上重啟服務

$computers = @("Server1", "Server2", "Server3")

Invoke-Command -ComputerName $computers -ScriptBlock { Restart-Service -Name "Spooler" }

範例:從本地腳本執行遠端指令

假設有一個本地腳本 C:\Scripts\Task.ps1,需要在遠端電腦上執行。

Invoke-Command -ComputerName 192.168.1.100 -FilePath "C:\Scripts\Task.ps1"

四、遠端命令與本機命令的差異

在遠端執行命令時,存在一些與本地執行的差異,需要特別注意。

反序列化物件

遠端命令返回的物件是「反序列化」的,這意味著它們僅包含屬性值,而沒有方法。這可能影響您對物件的操作,例如無法調用方法或修改屬性。

本機處理 vs. 遠端處理

為了提高效率,應盡量在遠端完成資料處理,減少傳輸到本地的數據量。例如,以下做法更有效:

遠端處理:

Invoke-Command -ComputerName Server1 -ScriptBlock { Get-EventLog -LogName System | Where-Object { $_.EventID -eq 100 } }

本地處理(效率較低):

$events = Invoke-Command -ComputerName Server1 -ScriptBlock { Get-EventLog -LogName System }
$filteredEvents = $events | Where-Object { $_.EventID -eq 100 }

在遠端進行過濾可以減少網路流量,提高執行速度。


參考文章

對應 30天挑戰精通 PowerShell 該書第 13 章「遠端控制:一對一及一對多」。
WinRM - setup and test on Windows laptop
Windows Remote Management Architecture
Powershell tricks—Powershell Remoting
about_PSSessions
PowerShell Remoting (PSRemoting) Explained: Ultimate Guide


明日主題

Day 16 - 利用背景作業進行多工處理


上一篇
Day 14 - 關於 PowerShell 遠端控制
下一篇
Day 16 - 利用背景作業進行多工處理
系列文
《30天挑戰精通 PowerShell:從 Windows Server 到 Azure DevOps 自動化之旅》30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言